winsafe\gui\native_controls/
tree_view_item.rs1use std::any::TypeId;
2use std::cell::RefCell;
3use std::mem::ManuallyDrop;
4use std::rc::Rc;
5
6use crate::co;
7use crate::decl::*;
8use crate::gui::{iterators::*, *};
9use crate::kernel::privs::*;
10use crate::msg::*;
11use crate::prelude::*;
12
13pub struct TreeViewItem<'a, T: 'static = ()> {
20 owner: &'a TreeView<T>,
21 hitem: HTREEITEM,
22}
23
24impl<'a, T> Clone for TreeViewItem<'a, T> {
25 fn clone(&self) -> Self {
26 Self {
27 owner: self.owner,
28 hitem: unsafe { self.hitem.raw_copy() },
29 }
30 }
31}
32
33impl<'a, T> TreeViewItem<'a, T> {
34 #[must_use]
35 pub(in crate::gui) const fn new(owner: &'a TreeView<T>, hitem: HTREEITEM) -> Self {
36 Self { owner, hitem }
37 }
38
39 pub fn add_child(&self, text: &str, icon_index: Option<u32>, data: T) -> SysResult<Self> {
43 self.owner
44 .raw_insert_item(Some(&self.hitem), text, icon_index, data)
45 }
46
47 #[must_use]
58 pub fn data(&self) -> SysResult<Rc<RefCell<T>>> {
59 if TypeId::of::<T>() == TypeId::of::<()>() {
60 panic!("TreeView<()> will hold no data."); }
62
63 let rc_ptr = self.data_lparam()?;
64 if rc_ptr.is_null() {
65 panic!("TreeViewItem with invalid index, no data.");
66 }
67
68 let rc_obj = ManuallyDrop::new(unsafe { Rc::from_raw(rc_ptr) });
69 Ok(Rc::clone(&rc_obj))
70 }
71
72 #[must_use]
73 pub(in crate::gui) fn data_lparam(&self) -> SysResult<*mut RefCell<T>> {
74 let mut tvix = TVITEMEX::default();
75 tvix.hItem = unsafe { self.hitem.raw_copy() };
76 tvix.mask = co::TVIF::PARAM;
77
78 unsafe {
79 self.owner
80 .hwnd()
81 .SendMessage(tvm::GetItem { tvitem: &mut tvix })?;
82 }
83
84 Ok(match tvix.lParam {
85 0 => std::ptr::null_mut(),
86 lp => lp as _,
87 })
88 }
89
90 pub fn delete(&self) -> SysResult<()> {
93 unsafe {
94 self.owner
95 .hwnd()
96 .SendMessage(tvm::DeleteItem { hitem: &self.hitem })
97 }
98 }
99
100 pub fn edit_label(&self) -> SysResult<HWND> {
105 unsafe {
106 self.owner
107 .hwnd()
108 .SendMessage(tvm::EditLabel { hitem: &self.hitem })
109 }
110 }
111
112 pub fn ensure_visible(&self) -> bool {
118 unsafe {
119 self.owner
120 .hwnd()
121 .SendMessage(tvm::EnsureVisible { hitem: &self.hitem })
122 != 0
123 }
124 }
125
126 pub fn expand(&self, expand: bool) -> SysResult<()> {
129 unsafe {
130 self.owner.hwnd().SendMessage(tvm::Expand {
131 hitem: &self.hitem,
132 action: if expand { co::TVE::EXPAND } else { co::TVE::COLLAPSE },
133 })
134 }
135 }
136
137 #[must_use]
139 pub const fn htreeitem(&self) -> &HTREEITEM {
140 &self.hitem
141 }
142
143 #[must_use]
146 pub fn is_expanded(&self) -> bool {
147 unsafe {
148 self.owner.hwnd().SendMessage(tvm::GetItemState {
149 hitem: &self.hitem,
150 mask: co::TVIS::EXPANDED,
151 })
152 }
153 .has(co::TVIS::EXPANDED)
154 }
155
156 #[must_use]
159 pub fn is_root(&self) -> bool {
160 self.parent().is_none()
161 }
162
163 #[must_use]
165 pub fn iter_children(&self) -> impl Iterator<Item = TreeViewItem<'a, T>> + 'a {
166 TreeViewChildItemIter::new(self.owner, Some(self.clone()))
167 }
168
169 #[must_use]
171 pub fn iter_next_siblings(&self) -> impl Iterator<Item = TreeViewItem<'a, T>> + 'a {
172 TreeViewItemIter::new(self.owner, Some(self.clone()), co::TVGN::NEXT)
173 }
174
175 #[must_use]
177 pub fn iter_prev_siblings(&self) -> impl Iterator<Item = TreeViewItem<'a, T>> + 'a {
178 TreeViewItemIter::new(self.owner, Some(self.clone()), co::TVGN::PREVIOUS)
179 }
180
181 #[must_use]
184 pub fn parent(&self) -> Option<Self> {
185 unsafe {
186 self.owner.hwnd().SendMessage(tvm::GetNextItem {
187 relationship: co::TVGN::PARENT,
188 hitem: Some(&self.hitem),
189 })
190 }
191 .map(|hitem| TreeViewItem::new(self.owner, hitem))
192 }
193
194 pub fn set_text(&self, text: &str) -> SysResult<()> {
197 let mut buf = WString::from_str(text);
198
199 let mut tvix = TVITEMEX::default();
200 tvix.hItem = unsafe { self.hitem.raw_copy() };
201 tvix.mask = co::TVIF::TEXT;
202 tvix.set_pszText(Some(&mut buf));
203
204 unsafe {
205 self.owner
206 .hwnd()
207 .SendMessage(tvm::SetItem { tvitem: &tvix })
208 }
209 }
210
211 #[must_use]
214 pub fn text(&self) -> SysResult<String> {
215 let mut tvix = TVITEMEX::default();
216 tvix.hItem = unsafe { self.hitem.raw_copy() };
217 tvix.mask = co::TVIF::TEXT;
218
219 let mut buf = WString::new_alloc_buf(MAX_PATH + 1); tvix.set_pszText(Some(&mut buf));
221
222 unsafe {
223 self.owner
224 .hwnd()
225 .SendMessage(tvm::GetItem { tvitem: &mut tvix })?;
226 }
227
228 Ok(buf.to_string())
229 }
230}